package com.qkl.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qkl.user.dto.ChangePasswordDto;
import com.qkl.user.dto.UserDto;
import com.qkl.user.dto.user.ForgetPasswordDto;
import com.qkl.user.entity.Problem;
import com.qkl.user.entity.User;
import com.qkl.user.entity.UserProblem;
import com.qkl.user.enums.ExceptionEnum;
import com.qkl.user.enums.ProblemEnum;
import com.qkl.user.exception.OperationException;
import com.qkl.user.mapper.ProblemMapper;
import com.qkl.user.mapper.UserMapper;
import com.qkl.user.mapper.UserProblemMapper;
import com.qkl.user.service.UserService;
import com.qkl.user.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private  PasswordEncoder passwordEncoder;
    @Autowired
    private ProblemMapper problemMapper;
    @Autowired
    private UserProblemMapper userProblemMapper;
    // 从配置文件中注入绝对路径
    @Value("${upload.base-path}")
    private String uploadBasePath;

    @Value("${upload.base-url}")
    private String uploadBaseUrl;
    public User getUserById() {
        return userMapper.selectById(JwtUtils.getUserId());
    }

    @Override
    public List<Problem> getProblems() {
        LambdaQueryWrapper<Problem> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(Problem::getId,Problem::getName).eq(Problem::getIsDel, ProblemEnum.EXIST).orderByDesc(Problem::getId);
        //users.stream().map(UserDTO::from).collect(Collectors.toList())
        return problemMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    public UserDto getUserDtoInviteCode(String inviteCode) {
        User user = userMapper.findUserByInviteCode(inviteCode);
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(user, userDto);
        return userDto;
    }

    @Override
    public UserDto getUserDtoId() {
        User user = userMapper.selectById(JwtUtils.getUserId());
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(user, userDto);
        return userDto;
    }

    @Override
    public String changeAvatar(MultipartFile file) {
       Long user_id =  JwtUtils.getUserId();
        // 2. 校验文件是否为空
        if (file.isEmpty()) {
            throw new OperationException(ExceptionEnum.FILE_NOT_EMPTY);
        }
// 1. 构建日期目录
        String dateDir = new SimpleDateFormat("yyyyMMdd").format(new Date());
        Path dateDirPath = Paths.get(uploadBasePath, dateDir);

        try {
            // 2. 强制创建目录（如果不存在）
            Files.createDirectories(dateDirPath);
        } catch (IOException e) {
            e.printStackTrace();
            throw new OperationException(ExceptionEnum.CREATE_DIRECTORY_FAIL);
        }

        // 3. 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String fileName = UUID.randomUUID().toString().replace("-", "") + suffix;

        // 4. 构建目标文件路径
        Path targetFilePath = dateDirPath.resolve(fileName);
        File targetFile = targetFilePath.toFile();

        try {
            // 5. 保存文件
            file.transferTo(targetFile);
        } catch (IOException e) {
            e.printStackTrace();
            throw new OperationException(ExceptionEnum.FILE_NOT_FAIL);
        }
        String avatar =  uploadBaseUrl+"/" + dateDir + "/" + fileName;
        User user = userMapper.selectById(user_id);
        user.setAvatar(avatar);
        userMapper.updateById(user);
        // 6. 构建图片访问URL
        // 由于我们配置了静态资源映射，URL 可以直接是 /static/日期目录/文件名
        return avatar;
    }

    @Override
    public boolean bindAddress(String address) {
        log.info("绑定地址：{}", address);
        if(address.isEmpty()){
            throw new OperationException(ExceptionEnum.ADDRESS_NOT_EXISTS);
        }
        Long userId = JwtUtils.getUserId();
        User user = userMapper.selectById(userId);
        if(user == null) {
            throw new OperationException(ExceptionEnum.USER_NOT_FOUND);
        }
        User user1 = getUserAddress( address);
        if(user1 != null){
            throw new OperationException(ExceptionEnum.ADDRESS_ALREADY_EXISTS);
        }
        user.setAddress(address);
        userMapper.updateById(user);
        return true;
    }

    @Override
    public User getUserAddress(String address) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getAddress, address);
        return userMapper.selectOne(lambdaQueryWrapper);
    }

    @Override
    public void changePassword(ChangePasswordDto changePasswordDto) {
        boolean isPassword = false;
        boolean isTradPassword = false;
        if(!changePasswordDto.getPassword().isEmpty() || !changePasswordDto.getPasswordTo().isEmpty()){
              if(!changePasswordDto.getPassword().equals(changePasswordDto.getPasswordTo())){
                  throw new OperationException(ExceptionEnum.PASSWORD_AND_PASSWORD);
              }
            isPassword = true;
        }
        if(!changePasswordDto.getTradPassword().isEmpty() || !changePasswordDto.getTradPasswordTo().isEmpty()){
            if(!changePasswordDto.getTradPassword().equals(changePasswordDto.getTradPasswordTo())){
                throw new OperationException(ExceptionEnum.TRADPASSWORD_AND_TRADPASSWORD);
            }
            isTradPassword = true;
        }
        if(!isPassword && !isTradPassword){
            throw new OperationException(ExceptionEnum.NO_UPDATE_OPERATION);
        }
        Long userId = JwtUtils.getUserId();
        //验证问题和答案
       LambdaQueryWrapper<UserProblem> lambdaQuery= new LambdaQueryWrapper<>();
       lambdaQuery.eq(UserProblem::getUserId, userId)
                .eq(UserProblem::getAnswerOne, changePasswordDto.getAnswerOne())
                .eq(UserProblem::getAnswerTwo, changePasswordDto.getAnswerTwo());
        UserProblem userProblem = userProblemMapper.selectOne(lambdaQuery);
        if(userProblem == null){
            throw new OperationException(ExceptionEnum.ONE_OR_TWO_ANSWER_ERROR);
        }
        User user = userMapper.selectById(userId);
        if(isPassword){
            String password = passwordEncoder.encode(changePasswordDto.getPassword());
            user.setPassword(password);
        }
        if(isTradPassword){
            String tradPassword = passwordEncoder.encode(changePasswordDto.getTradPassword());
            user.setTradPassword(tradPassword);
        }
        userMapper.updateById(user);
    }

    @Override
    public void forgetPassword(ForgetPasswordDto forgetPasswordDto) {
        if(!forgetPasswordDto.getPassword().equals(forgetPasswordDto.getPasswordTo())){
            throw new OperationException(ExceptionEnum.PASSWORD_AND_PASSWORD);
        }
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUsername, forgetPasswordDto.getUsername());
        User user = userMapper.selectOne(lambdaQueryWrapper);
        if(user == null){
            throw new OperationException(ExceptionEnum.USER_NOT_FOUND);
        }
        if(!forgetPasswordDto.getPassword().equals(forgetPasswordDto.getPasswordTo())){
            throw new OperationException(ExceptionEnum.PASSWORD_AND_PASSWORD);
        }
        //验证问题是否正确
        LambdaQueryWrapper<UserProblem> lambdaQuery= new LambdaQueryWrapper<>();
        lambdaQuery.eq(UserProblem::getUserId, user.getId())
                .eq(UserProblem::getAnswerOne, forgetPasswordDto.getAnswerOne())
                .eq(UserProblem::getAnswerTwo, forgetPasswordDto.getAnswerTwo())
                .eq(UserProblem::getProblemOneId, forgetPasswordDto.getQuestionOne())
                .eq(UserProblem::getProblemTwoId, forgetPasswordDto.getQuestionTwo())
        ;
       UserProblem userProblem = userProblemMapper.selectOne(lambdaQuery);
       if (userProblem == null){
           throw new OperationException(-1, "问题答案错误");
       }
        String password = passwordEncoder.encode(forgetPasswordDto.getPassword());
        user.setPassword(password);
        userMapper.updateById(user);
    }


}
